#ifndef TIEC_INTERNAL_PARSER_H
#define TIEC_INTERNAL_PARSER_H

#include "parser.h"

namespace NS_TIEC {
  /// 语法解析器实现
  class TiecodeParser : public Parser {
  public:
    explicit TiecodeParser(PTR<Context> context, PTR<TiecodeSource> source);

    PTR<CompilationUnitTree> parseCompilationUnit() override;

    PTR<StatementTree> parseStatement() override;

    PTR<ExpressionTree> parseExpression() override;

    PTR<ExpressionTree> parseType() override;

    PTR<CodeTree> parseCode() override;
  private:
    PTR<TiecodeSource> source_;
    PTR<Context> context_;
    NamePool* name_pool_;
    Options* options_;
    Messages* messages_;
    TiecodeLexer lexer_;

    //==============================解析时的临时变量==========================================
    UInt32 line_;
    UInt32 column_;
    UInt32 index_;
    int token_;
    WString comment_;
    List<PTR<AnnotationTree>> annotations_;
    Stack<int> expr_mode_stack_;
    //=============================静态变量定义========================================
    static constexpr int kExprModeInit = 0;
    static constexpr int kExprModeInvokeArgs = 1;
    static constexpr int kExprModeFormalParam = 2;
    static constexpr int kExprModeParen = 3;
    static constexpr int kExprModeArrayElements = 4;
    static constexpr int kExprModeArrayIndex = 5;
    static constexpr int kExprModeEventTarget = 6;
    static constexpr int kExprModeLoopArgs = 7;
    static constexpr int kExprModeIfArgs = 8;
    static constexpr int kExprModeBlockEnd = 9;
    //==============================内部方法==========================================
    List<PTR<AnnotationTree>> parseAnnotationList();
    PTR<AnnotationTree> parseAnnotation();
    PTR<ExpressionTree> parseAnnotationArg();
    PTR<ClassTree> parseClass();
    List<PTR<IdentifierTree>> parseClassTemplateArgs();
    PTR<ExpressionTree> parseClassExtendsClause();
    void parseClassBody(PTR<ClassTree> klass);
    PTR<IdentifierTree> parseName();
    PTR<ExpressionTree> parseFullName();
    void nextToken();
    void nextTokenSkipBlank();
    void nextTokenSkipLine();
    void accept(TiecodeToken token, const char* error_msg);
    void skip(bool stop_identifier, bool stop_paren, bool stop_space, bool stop_newline, bool stop_statement);
    void syntaxErrorFromStart(Position start_pos, const char* key, ...);
    void syntaxErrorToEnd(Position end_pos, const char* key, ...);
    Origin currentOrigin();
    Position currentPosition();
    void pushExprMode(int mode);
    void popExprMode();
    int currentExprMode();
  };
}
#endif //TIEC_INTERNAL_PARSER_H
